package com.gorillalogic.scrummonkey.test {
	import com.gorillalogic.scrummonkey.dms.Project;
	import com.gorillalogic.scrummonkey.dms.ProjectService;
	import com.gorillalogic.scrummonkey.dms.Release;
	import com.gorillalogic.scrummonkey.dms.ReleaseService;
	
	import mx.collections.ArrayCollection;
	
	import org.flexunit.Assert;
	import org.hamcrest.assertThat;
	import org.hamcrest.collection.hasItems;

	public class ReleaseTest extends BaseTest {

		/**
		 * Create a whole bunch of R under P and then verify success.
		 */
		[Test(async,order=1)]
		public function create():void {
			var p:Project = new Project('releasetest-proj1','desc-proj1');

			var r1:Release = new Release('rel1');
			var r2:Release = new Release('rel2');
			var r3:Release = new Release('rel3');
			var r4:Release = new Release('rel4');
			var r5:Release = new Release('rel5');
			var r6:Release = new Release('rel6');
			var r7:Release = new Release('rel7');
			var r8:Release = new Release('rel8');
			var r9:Release = new Release('rel9');
			var r10:Release = new Release('rel10');
			var r11:Release = new Release('rel11');
			var r12:Release = new Release('rel12');
			var r13:Release = new Release('rel13');
			var r14:Release = new Release('rel14');
			var r15:Release = new Release('rel15');
			var r16:Release = new Release('rel16');
			var r17:Release = new Release('rel17');
			var r18:Release = new Release('rel18');
			var r19:Release = new Release('rel19');
			var r20:Release = new Release('rel20');
			var r21:Release = new Release('rel21');
			var r22:Release = new Release('rel22');
			var r23:Release = new Release('rel23');
			var r24:Release = new Release('rel24');
			var r25:Release = new Release('rel25');
			var r26:Release = new Release('rel26');
			var r27:Release = new Release('rel27');
			var r28:Release = new Release('rel28');
			var r29:Release = new Release('rel29');
			var r30:Release = new Release('rel30');

			//wireup project & releases
			p.releases.addItem(r1);
			p.releases.addItem(r2);
			p.releases.addItem(r3);
			p.releases.addItem(r4);
			p.releases.addItem(r5);
			p.releases.addItem(r6);
			p.releases.addItem(r7);
			p.releases.addItem(r8);
			p.releases.addItem(r9);
			p.releases.addItem(r10);
			p.releases.addItem(r11);
			p.releases.addItem(r12);
			p.releases.addItem(r13);
			p.releases.addItem(r14);
			p.releases.addItem(r15);
			p.releases.addItem(r16);
			p.releases.addItem(r17);
			p.releases.addItem(r18);
			p.releases.addItem(r19);
			p.releases.addItem(r20);
			p.releases.addItem(r21);
			p.releases.addItem(r22);
			p.releases.addItem(r23);
			p.releases.addItem(r24);
			p.releases.addItem(r25);
			p.releases.addItem(r26);
			p.releases.addItem(r27);
			p.releases.addItem(r28);
			p.releases.addItem(r29);
			p.releases.addItem(r30);

			r1.project = p;
			r2.project = p;
			r3.project = p;
			r4.project = p;
			r5.project = p;
			r6.project = p;
			r7.project = p;
			r8.project = p;
			r9.project = p;
			r10.project = p;
			r11.project = p;
			r12.project = p;
			r13.project = p;
			r14.project = p;
			r15.project = p;
			r16.project = p;
			r17.project = p;
			r18.project = p;
			r19.project = p;
			r20.project = p;
			r21.project = p;
			r22.project = p;
			r23.project = p;
			r24.project = p;
			r25.project = p;
			r26.project = p;
			r27.project = p;
			r28.project = p;
			r29.project = p;
			r30.project = p;

			callAndThenOrFault(ProjectService.service.createProject(p), create2, null, 50000);
		}

		private function create2(data:Object, passThroughData:Object):void {
			callAndThenOrFault(ProjectService.service.getByName('releasetest-proj1'), create3);
		}

		private function create3(data:Object, passThroughData:Object):void {
			var project:Project = (data.result as ArrayCollection).getItemAt(0) as Project;
			Assert.assertEquals('Bad project name', 'releasetest-proj1', project.name);
			Assert.assertEquals('Bad project description', 'desc-proj1', project.description);

			//verify release
			Assert.assertEquals('Bad number of releases', 30, project.releases.length);

			var releaseNames:Array = project.releases.toArray().map(
				function (r:Release, idx:int, items:Array):String {
					return r.name;
				});

			assertThat('Bad release names', releaseNames,
				hasItems('rel1','rel2','rel3','rel4','rel5','rel6','rel7','rel8','rel9','rel10',
					'rel11','rel12','rel13','rel14','rel15','rel16','rel17','rel18','rel19','rel20',
					'rel21','rel22','rel23','rel24','rel25','rel26','rel27','rel28','rel29','rel30'));

			var release:Release = project.releases.getItemAt(0) as Release;
			Assert.assertNull('Bad release description', release.description);
			Assert.assertEquals("Bad release's project name", 'releasetest-proj1', release.project.name);
		}


		/**
		 * Cleanup P and all 30 R's
		 */
		[Test(async,order=2)]
		public function cleanup():void {
			callAndThenOrFault(ProjectService.service.getByName('releasetest-proj1'), cleanup2);
		}

		private function cleanup2(data:Object, passThroughData:Object):void {
			var project:Project = (data.result as ArrayCollection).getItemAt(0) as Project;
			Assert.assertEquals('Bad project name', 'releasetest-proj1', project.name);

			callAndThenOrFault(ProjectService.service.deleteProject(project), cleanup3);
		}

		private function cleanup3(data:Object, passThroughData:Object):void {
			callAndThenOrFault(ProjectService.service.getByName('releasetest-proj1'), cleanup4);
			callAndThenOrFault(ReleaseService.service.getByName('rel1'), cleanup4);
			callAndThenOrFault(ReleaseService.service.getByName('rel25'), cleanup4);
			callAndThenOrFault(ReleaseService.service.getByName('rel30'), cleanup4);
		}

		private function cleanup4(data:Object, passThroughData:Object):void {
			var entities:ArrayCollection = data.result as ArrayCollection;
			Assert.assertEquals('Cleanup failed', 0, entities.length);
		}
	}
}